//
//  FBtSession.m
//  JwPackDemo
//
//  Created by 陈警卫 on 2025/8/14.
//

#import "FBtSession.h"

#import "FBtManager.h"
#import "FBtSession+Decode.h"
#import "FBtSession+HSH.h"

@interface FBtSession ()

/// 接收数据分包缓存
@property (nonatomic, strong) NSMutableData *receiveCacheData;

/// 数据写入间隔(默认0.1s)
@property (nonatomic, assign) CGFloat writeInterval;

/// 将要发送数据数组
@property (nonatomic, strong) NSMutableArray<FBtMessageModel *> *sendMessageModels;

/// 已发送等待接收字典 @{messageModel.key: messageModel}
@property (nonatomic, strong) NSMutableDictionary *sendReceiveParams;

/// 消息发送轮巡计时器
@property (nonatomic, strong) CXGCDTimer *timerWrite;

@end

@implementation FBtSession

- (instancetype)init {
    self = [super init];
    if (self) {
        [self setupData];
    }
    return self;
}

- (void)setupData {
    [self resetBtSession];
}

/// 重置Session
- (void)resetBtSession {
    [self endTimerWrite];
    [self endTimerHeart];
    
    self.receiveCacheData = [NSMutableData data];
    self.writeInterval = 0.1;
    self.sendMessageModels = [NSMutableArray array];
    self.sendReceiveParams = [NSMutableDictionary dictionary];
}

#pragma mark - 数据处理
 
/// 接受数据
- (void)receiveData:(NSData *)data {
    if ([self isCompledData:data]) {
        // 正确数据解析数据
        [self handleCompledData:data];
    } else {
        // 错误数据处理分包
        NSLog(@"接收错误数据--%@", data);
        [self.receiveCacheData appendData:data];
        if (self.receiveCacheData.length >= 13) {
            [self handleSubcontract];
        }
    }
}

/// 验证数据
- (BOOL)isCompledData:(NSData *)data {
    BOOL isCompled = NO;
    if (data.length >= 13) {
        NSData *preData = [data subdataWithRange:(NSMakeRange(0, 2))];
        NSData *sufData = [data subdataWithRange:(NSMakeRange(data.length - 2, 2))];
        
        Byte perByte[2] = {0x7F, 0x7F};
        Byte sufByte[2] = {0xF7, 0xF7};
        Byte perByte_b[2] = {0x7E, 0x7E};
        Byte sufByte_b[2] = {0xE7, 0xE7};
        
        if ([preData isEqualToData:[NSData dataWithBytes:perByte length:sizeof(perByte)]] ||
            [sufData isEqualToData:[NSData dataWithBytes:sufByte length:sizeof(sufByte)]] ||
            [preData isEqualToData:[NSData dataWithBytes:perByte_b length:sizeof(perByte_b)]] ||
            [sufData isEqualToData:[NSData dataWithBytes:sufByte_b length:sizeof(sufByte_b)]]) {
            
            NSData *crcData = [data subdataWithRange:(NSMakeRange(data.length - 4, 2))];
            NSData *enData = [data subdataWithRange:(NSMakeRange(2, data.length - 6))];
            UInt16 order = [CJCRCHub computeCRC16WithData:enData type:(CJCRC16TypeModbus)];
            NSData *orderData = [NSData dataWithBytes:&order length:sizeof(order)];
            if ([crcData isEqualToData:orderData]) {
                isCompled = YES;
            } else {
                NSLog(@"CRC验证错误--%@", data);
            }
        }
    }
    return isCompled;
}


/// 处理正确数据
- (void)handleCompledData:(NSData *)data {
    Byte *byte = (Byte *)[data bytes];
    
    uint8_t func = byte[2];
    UInt16 length = (byte[7] >> 8) + (byte[8]);
    NSData *timeData = [data subdataWithRange:(NSMakeRange(3, 4))];

    NSData *valueData = nil;
    if (length > 0) {
        valueData = [data subdataWithRange:(NSMakeRange(9, length))];
    }
    
    NSLog(@"接收处理正确数据--%@", [data f_hexString]);
    
    NSString *key = [timeData f_hexString];
    FBtMessageModel *messageModel = self.sendReceiveParams[key];
    if (messageModel) {
        // 发送数据
        messageModel.r_value = valueData;
        messageModel.r_data = data;
        [self receiveDecodeWithModel:messageModel];
        // 回调结果
        messageModel.state = FBtMessageStateReplyed;
        if (messageModel.didReceiveAction) {
            messageModel.didReceiveAction(messageModel);
        }
        [self.sendReceiveParams removeObjectForKey:messageModel.key];
    } else {
        // 非发送数据
        FBtMessageModel *messageModel = [[FBtMessageModel alloc] init];
        messageModel.func = func;
        // 握手判断
        [self handshakeMessageModel:messageModel];
    }
}

/// 错误数据处理分包
- (void)handleSubcontract {
    if (self.receiveCacheData.length <= 0) {
        return;
    }
    // 遍历寻找包头 0x7F7F/0x7E7E
    Byte *byte = (Byte *)[self.receiveCacheData bytes];
    NSInteger index = -1;
    for (NSInteger i = 0; i < self.receiveCacheData.length - 1; i++) {
        if ((byte[i] == 0x7F && byte[i + 1] == 0x7F) || (byte[i] == 0x7E && byte[i + 1] == 0x7E)) {
            index = i;
            break;
        }
    }
    if (index == -1) {
        return;
    }
    // 定位长度位
    NSInteger l0 = index + 7;
    NSInteger l1 = index + 8;
    if (l1 > self.receiveCacheData.length) {
        return;
    }
    // 判断无效数据长度
    UInt16 valueLength = byte[l0] + (byte[l1] << 8);
    if (valueLength > 512) {
        NSRange cacheRange = NSMakeRange(index + 1, self.receiveCacheData.length - (index + 1));
        self.receiveCacheData = [NSMutableData dataWithData:[self.receiveCacheData subdataWithRange:cacheRange]];
        [self handleSubcontract];
        return;
    }
    // 判断缓存长度够不消息长度
    NSInteger messageLength = 9 + valueLength + 4;
    if ((index + messageLength) > self.receiveCacheData.length) {
        return;
    }
    // 完整数据
    NSData *compledData = [self.receiveCacheData subdataWithRange:(NSMakeRange(index, messageLength))];
    if ([self isCompledData:compledData]) {
        [self handleCompledData:compledData];
        index = index + compledData.length;
    }
    // 下一轮循环
    NSRange cacheRange = NSMakeRange(index + 1, self.receiveCacheData.length - (index + 1));
    self.receiveCacheData = [NSMutableData dataWithData:[self.receiveCacheData subdataWithRange:cacheRange]];
    [self handleSubcontract];
}


#pragma mark - 数据发送

/// 开始写入计时器
- (void)startTimerWrite {
    if (self.timerWrite) {
        return;
    }
    __weak typeof(self) wself = self;
    self.timerWrite = [CXGCDTimer startWithInterval:self.writeInterval handler:^{
        [wself timerWriteAction];
    }];
}

/// 结束写入计时器
- (void)endTimerWrite {
    [self.timerWrite stop];
    self.timerWrite = nil;
}

/// 计时写入数据
- (void)timerWriteAction {
    if (self.sendMessageModels.count > 0) {
        [self writeLoopAction];
    } else {
        [self endTimerWrite];
    }
}

/// 写入数据循环
- (void)writeLoopAction {
    if (self.sendMessageModels.count > 0) {
        FBtMessageModel *messageModel = [self.sendMessageModels firstObject];
        [self writeMessageModel:messageModel];
        if (self.sendMessageModels.count) {
            [self.sendMessageModels removeObjectAtIndex:0];
        }
    }
}

/// 蓝牙写入数据
- (void)writeMessageModel:(FBtMessageModel *)messageModel {
    NSData *data = messageModel.data;
    CBPeripheral *peri = messageModel.periModel.peri;
    CBCharacteristic *chara = messageModel.periModel.writeChara;
    
    CBCharacteristicWriteType type = CBCharacteristicWriteWithoutResponse;
    if (messageModel.writeType == FBtMessageWriteTypeWithoutResponse) {
        type = CBCharacteristicWriteWithoutResponse;
    } else if (messageModel.writeType == FBtMessageWriteTypeResponse) {
        type = CBCharacteristicWriteWithResponse;
    }
    
    if (data && peri && chara) {
        NSLog(@"发送数据--%@", [messageModel.data f_hexString]);
        messageModel.state = FBtMessageStateSended;
        // 启动消息自身计时器
        __weak typeof(self) wself = self;
        [messageModel startTimerWithAction:^(FBtMessageModel *messageModel) {
            [wself sendTimeoutWithMessageModel:messageModel];
        }];
        
        // 持有消息对象
        if (messageModel.key) {
            self.sendReceiveParams[messageModel.key] = messageModel;
        }
        // 写入消息数据
        [peri writeValue:data forCharacteristic:chara type:type];
    }
}

/// 超时处理
- (void)sendTimeoutWithMessageModel:(FBtMessageModel *)messageModel {
    if (messageModel.key) {
        [self.sendReceiveParams removeObjectForKey:messageModel.key];
    }
    if (messageModel.didReceiveAction) {
        messageModel.didReceiveAction(messageModel);
    }
}

/// 发送数据
- (void)sendWithMessageModel:(FBtMessageModel *)messageModel {
    // 设置当前连接外设
    messageModel.periModel = [[FBtManager shared] currentPeriModel];
    
    if (messageModel.level == FBtMessageLevelPrior) {
        [self.sendMessageModels insertObject:messageModel atIndex:0];
    } else {
        [self.sendMessageModels addObject:messageModel];
    }
    [self startTimerWrite];
}

@end


